package org.datamining.guha.model.node;

import java.util.LinkedList;
import java.util.List;

import org.datamining.guha.model.Formatter;
import org.datamining.guha.model.PatternTreeModel;
import org.datamining.guha.model.literal.Literal;

/**
 * Pattern tree is a prefix tree made of nodes. All branches of the tree are of
 * the same length (the same number of nodes). Every node can have one to many
 * successor
 * 
 * @see PatternTreeModel
 * @author Lukas Vlcek
 * 
 */
public interface Node extends Comparable<Node> {

	/** When comparing nodes then only literal value matters. */
	public int compareTo(Node o);

	/** @return Parent node. */
	public Node getParent();

	/** @return frequency of literal in this node. */
	public long getFrequency();

	/**
	 * Set frequency on literal in this node to given value.
	 * 
	 * @param frequency
	 */
	public void setFrequency(long frequency);

	/**
	 * Increse frequency in this node.
	 * 
	 * @param increaseFactor
	 *            increase factor
	 */
	public void increaseFrequency(long increaseFactor);

	/**
	 * Distance between root and this node. If this node is direct child of Root
	 * then it returns one.
	 * 
	 * @return int Number of Nodes in the way up to the root.
	 */
	public int getDepth();

	/**
	 * Increase frequency by given value in all nodes from this node inclusive
	 * up to the root node.
	 * 
	 * @param increaseFactor
	 *            increase factor
	 * @see Node#increaseFrequency(long)
	 */
	public void increaseFrequencyUpToRoot(long increaseFactor);

	/**
	 * Checks if there is given pattern in the way up to Root. Searching starts
	 * from this.parent.
	 * 
	 * @param tree
	 *            Node which must be ordered reversely to frList otherwise
	 *            result is unpredictable.
	 */
	public boolean containsPatterUpToRoot(Node tree);

	/**
	 * If there is no parent Node then return true. Otherwise return false.
	 */
	public boolean isRoot();

	/** Set parent node. */
	public void setParent(Node n);

	/** @return list of all successors */
	public LinkedList<Node> getSuccessors();

	public void setSuccessors(LinkedList<Node> successors);

	/** @return Node at i-th position */
	public Node getSuccessor(int i);

	/** Sets i-th successor to given Node */
	public void setSuccessor(int i, Node n);

	/**
	 * Add new Node into successors List. Position of new node depends on
	 * implementation.
	 */
	public void addSuccessor(Node n);

	/**
	 * @return "next" Node having the same Literal. "Next" is such Node having
	 *         current Node in previousLiteralNode.
	 */
	public Node getNextLiteralNode();

	public void setNextLiteralNode(Node nextLiteralNode);

	/**
	 * @return "previous" Node having the same Literal. "Previous" is such Node
	 *         having current Node in nextLiteralNode.
	 */
	public Node getPreviousLiteralNode();

	public void setPreviousLiteralNode(Node previousLiteralNode);

	/** @return Listeral contained in this node. */
	public Literal getLiteral();

	/** Set Literal for this node. */
	public void setLiteral(Literal literal);

	public List<Node> getNodesWithLiteral(Literal l);

	/**
	 * This method finds out all "last" Nodes (or leaves if you like) which have
	 * this Node as direct or undirect parent. Can be applied on any node
	 * including root.
	 * 
	 * @return List of Node(s).
	 */
	public List<Node> getLastChilds();

	/** @return Node last successor of node */
	public Node getLastSuccessor();

	/** @return Node previous successor of node */
	public Node getPreviousSuccessor();

	/** Uses Formatter for output */
	public String toString();
	
	public void setFormatter(Formatter<Node> f);
	
	public Formatter<Node> getFormatter();

}
